package cn.com.libertymutual.sp.service.impl;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.mail.MessagingException;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.beust.jcommander.internal.Maps;
import com.google.common.collect.Lists;

import cn.com.libertymutual.core.email.IEmailService;
import cn.com.libertymutual.core.redis.util.RedisUtils;
import cn.com.libertymutual.core.util.BeanUtilExt;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.Current;
import cn.com.libertymutual.core.util.DateUtil;
import cn.com.libertymutual.core.util.RedPacketsUtil;
import cn.com.libertymutual.core.util.StringUtil;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.bean.SysOperationLog;
import cn.com.libertymutual.sp.bean.TbSpActivity;
import cn.com.libertymutual.sp.bean.TbSpApplicant;
import cn.com.libertymutual.sp.bean.TbSpApprove;
import cn.com.libertymutual.sp.bean.TbSpDrawLog;
import cn.com.libertymutual.sp.bean.TbSpFlow;
import cn.com.libertymutual.sp.bean.TbSpFlowDetail;
import cn.com.libertymutual.sp.bean.TbSpOrder;
import cn.com.libertymutual.sp.bean.TbSpProduct;
import cn.com.libertymutual.sp.bean.TbSpSaleLog;
import cn.com.libertymutual.sp.bean.TbSpScore;
import cn.com.libertymutual.sp.bean.TbSpScoreConfig;
import cn.com.libertymutual.sp.bean.TbSpScoreLogIn;
import cn.com.libertymutual.sp.bean.TbSpScoreLogOut;
import cn.com.libertymutual.sp.bean.TbSpUser;
import cn.com.libertymutual.sp.dao.ActivityDao;
import cn.com.libertymutual.sp.dao.ApplicantDao;
import cn.com.libertymutual.sp.dao.ApproveDao;
import cn.com.libertymutual.sp.dao.DrawLogDao;
import cn.com.libertymutual.sp.dao.FlowDao;
import cn.com.libertymutual.sp.dao.FlowDetailDao;
import cn.com.libertymutual.sp.dao.OperationLogDao;
import cn.com.libertymutual.sp.dao.OrderDao;
import cn.com.libertymutual.sp.dao.ProductDao;
import cn.com.libertymutual.sp.dao.ScoreConfigDao;
import cn.com.libertymutual.sp.dao.ScoreDao;
import cn.com.libertymutual.sp.dao.ScoreLogInDao;
import cn.com.libertymutual.sp.dao.ScoreLogOutDao;
import cn.com.libertymutual.sp.dao.SpSaleLogDao;
import cn.com.libertymutual.sp.dao.UserDao;
import cn.com.libertymutual.sp.req.DrawReq;
import cn.com.libertymutual.sp.service.api.ActivityService;
import cn.com.libertymutual.sp.service.api.BranchSetService;
import cn.com.libertymutual.sp.service.api.HomePageService;
import cn.com.libertymutual.sp.service.api.SmsService;
import cn.com.libertymutual.sys.dao.ISysRoleUserDao;
import cn.com.libertymutual.wx.common.MessageType;
import cn.com.libertymutual.wx.service.WeChatService;

@Service("activityService")
@RefreshScope // 刷新配置无需重启服务
public class ActivityServiceImpl implements ActivityService {

	private Logger log = LoggerFactory.getLogger(getClass());

	/** 新春大聚惠——产品ID列表 */
	@Value("${activity.productIds}")
	private String[] productIds;

	/** 新春大聚惠——分享标题 */
	@Value("${activity.greatBenefit.title}")
	private String title;

	/** 新春大聚惠——分享描述 */
	@Value("${activity.greatBenefit.desc}")
	private String desc;

	/** 新春大聚惠——分享标题图片*/
	@Value("${activity.greatBenefit.imgUrl}")
	private String imgUrl;

	@Autowired
	private OperationLogDao operationLogDao;
	@Autowired
	private SpSaleLogDao spSaleLogDao;
	@Autowired
	private ScoreConfigDao scoreConfigDao;
	@Autowired
	private ActivityDao activityDao;
	@Autowired
	private HomePageService homePageService;
	@Resource
	private SmsService SmsService;
	@Autowired
	private BranchSetService branchSetService;
	@Autowired
	private ApplicantDao applicantDao;
	@Autowired
	private OrderDao orderDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private DrawLogDao drawLogDao;
	@Autowired
	private ScoreLogInDao scoreLogInDao;
	@Autowired
	private ApproveDao approveDao;
	@Autowired
	private ScoreDao scoreDao;
	@Autowired
	private ScoreLogOutDao scoreLogOutDao;
	@Autowired
	private ProductDao productDao;
	@Resource
	private RedisUtils redisUtils;
	@Resource
	private IEmailService emailService;
	@Autowired
	private WeChatService weChatService;
	@Autowired
	private NamedParameterJdbcTemplate readJdbcTemplate2;
	@Autowired
	private FlowDetailDao flowDetailDao;
	@Autowired
	private FlowDao flowDao;
	@Autowired
	private ISysRoleUserDao roleUserDao;
	// @Override
	// public ServiceResult activityList(String activityName, String planStartTime,
	// String planEndTime, String status, int pageNumber, int pageSize) {
	// // TODO 活动发放规则列表
	// ServiceResult sr = new ServiceResult();
	// List<Order> orders = new ArrayList<Order>();
	// orders.add(new Order(Direction.ASC, "status"));
	// orders.add(new Order(Direction.DESC, "id"));
	// Sort sort = new Sort(orders);
	// Page<TbSpActivity> page = activityDao.findAll(new
	// Specification<TbSpActivity>() {
	// public Predicate toPredicate(Root<TbSpActivity> root, CriteriaQuery<?> query,
	// CriteriaBuilder cb) {
	// List<Predicate> predicate = new ArrayList<Predicate>();
	// if (StringUtils.isNotEmpty(activityName)) {
	// log.info(activityName);
	// predicate.add(cb.like(root.get("activityName").as(String.class), "%" +
	// activityName + "%"));
	// }
	// if (StringUtils.isNotEmpty(planStartTime)) {
	// log.info(planStartTime);
	// predicate.add(cb.greaterThanOrEqualTo(root.get("planStartTime").as(String.class),
	// planStartTime));
	// }
	// if (StringUtils.isNotEmpty(planEndTime)) {
	// log.info(planEndTime);
	// predicate.add(cb.lessThanOrEqualTo(root.get("planEndTime").as(String.class),
	// planEndTime));
	// }
	// if (StringUtils.isNotEmpty(status) && !"-1".equals(status)) {
	// log.info(status);
	// predicate.add(cb.equal(root.get("status").as(String.class), status));
	// }
	//
	// Predicate[] pre = new Predicate[predicate.size()];
	// return query.where(predicate.toArray(pre)).getRestriction();
	// }
	// }, PageRequest.of(pageNumber - 1, pageSize, sort));
	//
	// List<TbSpActivity> list = page.getContent();
	// if (null != page.getContent() && page.getContent().size() != 0) {
	// TbSpApprove tsa = null;
	// for (TbSpActivity activity : list) {
	// tsa = approveDao.findByTypeAndApproveId(Constants.ACTIVITY_APPROVE,
	// activity.getId(),
	// Constants.APPROVE_WAIT);
	// if (null != tsa) {
	// activity.setApprove(tsa);
	// }
	// tsa = approveDao.findByTypeAndApproveId(Constants.ACTIVITY_STOP_APPROVE,
	// activity.getId(),
	// Constants.APPROVE_WAIT);
	// if (null != tsa) {
	// activity.setApprove(tsa);
	// }
	// tsa = approveDao.findByTypeAndApproveId(Constants.BUDGET_APPROVE,
	// activity.getId(),
	// Constants.APPROVE_WAIT);
	// if (null != tsa) {
	// activity.setApprove(tsa);
	// }
	// }
	// }
	//
	// sr.setResult(page);
	// return sr;
	// }

	@Override
	public ServiceResult activityList(String activityName, String planStartTime, String planEndTime, String activityCode, String status,
			int pageNumber, int pageSize) {
		// TODO 活动发放规则列表
		ServiceResult sr = new ServiceResult();
		StringBuilder sql = new StringBuilder();
		StringBuilder endsql = null;
		String userId = Current.userId.get();
		Integer roleId = roleUserDao.findByUserid(userId).getRoleid();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Integer sqlPageNumber = (pageNumber - 1) * pageSize;
		sql.append("select * from tb_sp_activity ");
		// 条件
		if (StringUtils.isNotEmpty(activityName) || StringUtils.isNotEmpty(activityCode) || StringUtils.isNotEmpty(planStartTime)
				|| StringUtils.isNotEmpty(planEndTime) || StringUtils.isNotEmpty(status)) {
			sql.append(" where ");

			if (StringUtils.isNotEmpty(activityName)) {
				sql.append(" actvity_name  like :activityName and");
				paramMap.put("activityName", "%" + activityName + "%");
			}
			if (StringUtils.isNotEmpty(planStartTime)) {
				sql.append(" plan_starttime  >= :planStartTime and");
				paramMap.put("planStartTime", planStartTime);
			}
			if (StringUtils.isNotEmpty(planEndTime)) {
				sql.append(" plan_endtime  <=:planEndTime and");
				paramMap.put("planEndTime", planEndTime);
			}
			if (StringUtils.isNotEmpty(activityCode)) {
				sql.append(" activity_code  like :activityCode and");
				paramMap.put("activityCode", "%" + activityCode + "%");
			}
			if (StringUtils.isNotEmpty(status)) {
				sql.append(" status =:status and");
				paramMap.put("status", status);
			}

			endsql = new StringBuilder(sql.toString().substring(0, sql.toString().length() - 3));
			log.info("======endsql===={}", endsql.toString());

		} else {
			endsql = sql;
		}
		endsql.append(" ORDER BY FIELD(`status`,'2','3','4','1','5','6','7','0')");
		endsql.append(" limit :sqlPageNumber,:pageSize");
		paramMap.put("sqlPageNumber", sqlPageNumber);
		paramMap.put("pageSize", pageSize);
		log.info("======endsql===={}", endsql.toString());
		List<Map<String, Object>> list = readJdbcTemplate2.queryForList(endsql.toString(), paramMap);
		List<TbSpActivity> returnList = Lists.newArrayList();
		for (int i = 0; i < list.size(); i++) {// 遍历设置实体
			TbSpApprove tsa = null;
			TbSpActivity ac = new TbSpActivity();
			ac.setId((Integer) list.get(i).get("ID"));
			ac.setActivityCode((String) list.get(i).get("activity_code"));
			ac.setActivityName((String) list.get(i).get("actvity_name"));
			ac.setActivityType((String) list.get(i).get("activity_type"));
			ac.setAmountLimitation((Double) list.get(i).get("amount_limitation"));
			ac.setHasRemind((String) list.get(i).get("hasRemind"));
			ac.setTouchOffType((String) list.get(i).get("touchOff_type"));
			ac.setMinValue((Double) list.get(i).get("MIN_VALUE"));
			ac.setMaxTimes((Integer) list.get(i).get("MAX_VALUE"));
			ac.setSpecialTimes((Integer) list.get(i).get("SPECIAL_TIMES"));
			ac.setSpecialValue((Double) list.get(i).get("SPECIAL_VALUE"));
			ac.setBranchCode((String) list.get(i).get("branch_code"));
			ac.setDrawBalance((Integer) list.get(i).get("draw_balance"));
			ac.setDrawTimes((Integer) list.get(i).get("draw_times"));
			ac.setStatus((String) list.get(i).get("status"));
			ac.setSumBudget((Double) list.get(i).get("sum_budget"));
			ac.setBalanceBudget((Double) list.get(i).get("balance_budget"));
			ac.setPlanStartTime((Date) list.get(i).get("plan_starttime"));
			ac.setPlanEndTime((Date) list.get(i).get("plan_endtime"));
			ac.setActualStartTime((Date) list.get(i).get("actual_starttime"));
			ac.setActualEndTime((Date) list.get(i).get("actual_endtime"));
			ac.setWarnBalance((Double) list.get(i).get("warn_balance"));
			ac.setWarnPhoneNo((String) list.get(i).get("warn_phoneno"));
			ac.setWarnEmail((String) list.get(i).get("warn_email"));
			ac.setApplyer((String) list.get(i).get("applyer"));
			ac.setApplyTime((Date) list.get(i).get("apply_time"));
			ac.setApprover((String) list.get(i).get("approver"));
			ac.setApproveTime((Date) list.get(i).get("approve_time"));
			ac.setStopApplyer((String) list.get(i).get("stop_applyer"));
			ac.setStopApplyTime((Date) list.get(i).get("stop_applytime"));
			ac.setStopApprover((String) list.get(i).get("stop_approver"));
			ac.setStopApproveTime((Date) list.get(i).get("stop_approvetime"));
			ac.setPolicyRate((Double) list.get(i).get("POLICY_RATE"));
			ac.setRemark((String) list.get(i).get("remak"));
			ac.setActivityScript((String) list.get(i).get("activity_script"));
			tsa = approveDao.findApproveFlow(Constants.ACTIVITY_APPROVE, ac.getId().toString(), Constants.APPROVE_WAIT, Constants.FLOW_ACTIVITY);
			if (null != tsa) {
				ac.setApprove(tsa);
			}
			tsa = approveDao.findApproveFlow(Constants.ACTIVITY_STOP_APPROVE, ac.getId().toString(), Constants.APPROVE_WAIT, Constants.FLOW_ACTIVITY);
			if (null != tsa) {
				ac.setApprove(tsa);
			}
			tsa = approveDao.findApproveFlow(Constants.BUDGET_APPROVE, ac.getId().toString(), Constants.APPROVE_WAIT, Constants.FLOW_ACTIVITY);
			if (null != tsa) {
				ac.setApprove(tsa);
			}

			if (null != ac.getApprove()) {
				TbSpFlowDetail flowDetail = flowDetailDao.findByNoAndNode(ac.getApprove().getFlowNo(), ac.getApprove().getFlowNode());
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getUserCode())) {// 用户审批
					String[] users = flowDetail.getUserCode().split("&");
					boolean b = Arrays.asList(users).contains(userId);
					if (b) {
						ac.setApproveAuth("true");
					} else {
						ac.setApproveAuth("false");
					}
				}
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getRoleCode())) {// 角色审批
					String[] roles = flowDetail.getRoleCode().split("&");
					boolean b = Arrays.asList(roles).contains(roleId.toString());
					if (b) {
						ac.setApproveAuth("true");
					} else {
						ac.setApproveAuth("false");
					}
				}
			}
			returnList.add(ac);
		}
		Map<String, Object> map = new HashMap<String, Object>();
		Integer i = activityDao.findTotalActivity();
		map.put("list", returnList);
		map.put("total", i);
		sr.setResult(map);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult issueActivity(TbSpActivity activity) {
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_ACTIVITY);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		String userId = Current.userInfo.get().getUserId();
		if (null == activity.getId()) {// 添加
			log.info("---------添加活动-----------");
			activity.setStatus(Constants.APPROVE_VALID);
			activity.setBalanceBudget(activity.getSumBudget());
			activity.setApplyer(userId);
			activity.setDrawBalance(activity.getDrawTimes());
			activity.setActivityCode("AC" + DateUtil.dateFromat(new Date(), DateUtil.DATE_TIME_PATTERN4));
			activity.setApplyTime(new Date());
			activity.setHasRemind(Constants.FALSE);
			activityDao.save(activity);
			// 审批记录
			activity.setId(activity.getId());
			TbSpActivity newac = new TbSpActivity();
			try {
				BeanUtilExt.copyProperties(newac, activity);
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
			newac.setStatus(Constants.TRUE);
			String jsonstring = JSONObject.toJSONString(newac, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
			TbSpApprove tsa = new TbSpApprove();
			tsa.setStatus(Constants.FALSE);
			tsa.setApproveId(activity.getId().toString());
			tsa.setContent(jsonstring);
			tsa.setFlowNo(flow.getFlowNo());
			tsa.setFlowType(Constants.FLOW_ACTIVITY);
			tsa.setFlowNode(flow.getLastFlowNode());
			tsa.setOriginalStatus(Constants.FALSE);
			tsa.setApplyTime(new Date());
			tsa.setApplyUser(userId);
			tsa.setType(Constants.ACTIVITY_APPROVE);
			approveDao.save(tsa);
			// 记录日志
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("1");
			operLog.setModule("活动管理");
			operLog.setOperationTime(new Date());
			operLog.setUserId(userId);
			operLog.setContent("申请添加活动-ID:" + activity.getId());
			operationLogDao.save(operLog);
		} else {// 修改活动
			log.info("---------修改活动-----------");

		}
		return sr;
	}

	@Override
	public ServiceResult addBudget(DrawReq drawReq) {
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_ACTIVITY);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		String userId = Current.userInfo.get().getUserId();
		if (null == drawReq.getId() || null == drawReq.getBudget()) {
			sr.setFail();
			sr.setResult("请求参数不能为空！");
			return sr;
		}
		TbSpActivity dbactivity = activityDao.findById(drawReq.getId()).get();
		BigDecimal s = new BigDecimal(dbactivity.getBalanceBudget());
		BigDecimal b = new BigDecimal(drawReq.getBudget());
		if (500 > (s.add(b).doubleValue())) {
			sr.setFail();
			sr.setResult("提交后活动余额已不足500！");
			return sr;
		}

		if (null != drawReq.getAddDrawTimes() && null != drawReq.getAddSpecialTimes()) {// 抽奖活动
			BigDecimal dbD = new BigDecimal(dbactivity.getDrawBalance());
			BigDecimal dbS = new BigDecimal(dbactivity.getSpecialTimes());
			BigDecimal reS = new BigDecimal(drawReq.getAddSpecialTimes());
			BigDecimal reD = new BigDecimal(drawReq.getAddDrawTimes());
			if (0 > (reD.add(dbD).doubleValue()) || 0 > (reS.add(dbS).doubleValue())) {
				sr.setFail();
				sr.setResult("提交后剩余数不能小于0！");
				return sr;
			}
		}
		// 修改状态为待审批预算
		activityDao.updateStatus(Constants.APPROVE_BUDGET, drawReq.getId());
		// 创建审批记录
		TbSpApprove tsa = new TbSpApprove();
		tsa.setStatus(Constants.FALSE);
		tsa.setApproveId(drawReq.getId().toString());
		String jsonstring = JSONObject.toJSONString(drawReq, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
		tsa.setContent(jsonstring);
		tsa.setApplyTime(new Date());
		tsa.setOriginalStatus(dbactivity.getStatus());
		tsa.setApplyUser(Current.userInfo.get().getUserId());
		tsa.setType(Constants.BUDGET_APPROVE);
		tsa.setFlowNo(flow.getFlowNo());
		tsa.setFlowType(Constants.FLOW_ACTIVITY);
		tsa.setFlowNode(flow.getLastFlowNode());
		approveDao.save(tsa);
		// 记录日志
		SysOperationLog operLog = new SysOperationLog();
		operLog.setIP(Current.IP.get());
		operLog.setLevel("1");
		operLog.setModule("活动管理");
		operLog.setOperationTime(new Date());
		operLog.setUserId(userId);
		operLog.setContent("申请添加预算-ID:" + drawReq.getId() + ",预算额：" + drawReq.getBudget());
		operationLogDao.save(operLog);
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult stopActivity(Integer id) {
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_ACTIVITY);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		String userId = Current.userInfo.get().getUserId();
		TbSpActivity dbactivity = activityDao.findById(id).get();
		if (Constants.TRUE.equals(dbactivity.getStatus())) {
			TbSpApprove tsa = new TbSpApprove();
			tsa.setStatus(Constants.FALSE);
			tsa.setApproveId(id.toString());
			tsa.setApplyTime(new Date());
			tsa.setOriginalStatus(Constants.TRUE);
			tsa.setApplyUser(userId);
			tsa.setFlowNo(flow.getFlowNo());
			tsa.setFlowType(Constants.FLOW_ACTIVITY);
			tsa.setFlowNode(flow.getLastFlowNode());
			tsa.setType(Constants.ACTIVITY_STOP_APPROVE);
			approveDao.save(tsa);

			// 修改状态为待审批预算
			dbactivity.setStatus(Constants.APPROVE_STOP);
			dbactivity.setStopApplyer(userId);
			dbactivity.setStopApplyTime(new Date());
			activityDao.save(dbactivity);
			// 记录日志
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("3");
			operLog.setModule("活动管理");
			operLog.setOperationTime(new Date());
			operLog.setUserId(userId);
			operLog.setContent(userId + "申请停止活动-ID:" + id);
			operationLogDao.save(operLog);
		} else {
			sr.setFail();
			sr.setResult("不可停止非有效活动！");
		}

		return sr;
	}

	@Override
	public Map<String, Object> grantScore(String branchNo, String type, String userCode, TbSpOrder spOrder) {
		Map<String, Object> resultMap = Maps.newHashMap();
		List<TbSpScoreLogIn> acList = Lists.newArrayList();
		List<Map<String, Object>> sendMsgList = Lists.newArrayList();
		log.info("---------开始活动奖励---------");
		log.info("---------userCode---------{}", userCode);
		if (StringUtils.isEmpty(branchNo)) {// 机构不能为空
			return resultMap;
		}

		if (StringUtils.isEmpty(userCode)
				&& (null == spOrder || (StringUtils.isEmpty(spOrder.getUserId()) && StringUtils.isEmpty(spOrder.getRefereeId())))) {// 未指定发放积分对象
			return resultMap;
		}

		branchNo = branchSetService.cutBranchCode(branchNo);
		log.info("---------substring branchNo---------{}", branchNo);
		List<TbSpActivity> activitys = activityDao.findByBranchNo(branchNo);
		if (CollectionUtils.isEmpty(activitys)) {// 该机构没有活动
			log.info("---------无活动---------");
			return resultMap;
		}
		log.info("---------活动个数---------{}", activitys.size());

		List<TbSpScoreConfig> scoreconfig = (List<TbSpScoreConfig>) redisUtils.get(Constants.SCORE_CONFIG_INFO);
		if (CollectionUtils.isEmpty(scoreconfig)) {
			scoreconfig = scoreConfigDao.findAllConfig();
			redisUtils.set(Constants.SCORE_CONFIG_INFO, scoreconfig);
		}
		BigDecimal sumScore = new BigDecimal("0");
		A: for (TbSpActivity ac : activitys) {
			String sql = ac.getActivityScript();
			log.info("---------活动奖励sql---------{}", sql);
			if (StringUtils.isEmpty(sql)) {// 没有执行脚本
				continue;
			}
			if (!type.equals(ac.getTouchOffType())) {
				log.info("---------活动触发类型不匹配--执行下一个活动----{}-{}--", type, ac.getTouchOffType());
				continue;
			}
			// 生成积分记录
			if (null != spOrder) {// 用户编码为空，则查询订单信息
				log.info("=============出单活动 spOrder.getRefereeId()========={}", spOrder.getRefereeId());
				if (StringUtils.isNotEmpty(spOrder.getRefereeId())) {
					userCode = spOrder.getRefereeId();
				} else {
					userCode = spOrder.getUserId();
				}

			}
			TbSpUser ruser = userDao.findByUserCode(userCode);
			if (null == ruser) {
				log.info("-----不存在用户:{}-不获得积分-----", userCode);
				continue;
			}
			if (StringUtils.isBlank(ruser.getIdNumber())) {
				log.info("-----未实名-不获得积分-----{}");
				continue;
			}
			if (Constants.FALSE.equals(ruser.getStoreFlag())) {
				log.info("-----未开店-不获得积分-----{}");
				continue;
			}
			if (null != spOrder) {
				List<TbSpApplicant> applicant = applicantDao.findByOrderNo(spOrder.getOrderNo());
				if (CollectionUtils.isNotEmpty(applicant)) {
					B: for (TbSpApplicant at : applicant) {
						log.info(at.getCarId());
						if (at.getCarId().equals(ruser.getIdNumber())) {
							log.info("-----积分用户投保人、被保人是本人不获得积分------{}");
							continue A;
						}
					}
				}
			}
			List<Map<String, Object>> list = null;
			Map<String, Object> paramMap = new HashMap<String, Object>();
			if (-1 != sql.indexOf(":orderNo") && null != spOrder && StringUtils.isNotEmpty(spOrder.getOrderNo())) {// 存在订单号，出单活动
				log.info("---------sql put orderNo---------");
				paramMap.put("orderNo", spOrder.getOrderNo());

			}

			if (-1 != sql.indexOf(":userCode") && StringUtils.isNotEmpty(userCode)) {// 登录、完善信息、以及用户行为有关的活动
				log.info("---------sql put userCode---------");
				paramMap.put("userCode", userCode);
			}
			if (-1 != sql.indexOf(":id")) {
				log.info("---------sql put id---------");
				paramMap.put("id", ac.getId());
			}
			if (-1 != sql.indexOf(":activityCode")) {
				log.info("---------sql put activityCode---------");
				paramMap.put("activityCode", ac.getActivityCode());
			}
			if (-1 != sql.indexOf(":orderNo")) {
				if (null == spOrder) {
					continue;
				} else {
					if (StringUtils.isEmpty(spOrder.getOrderNo())) {
						continue;
					}
				}
			}
			if (-1 != sql.indexOf(":userCode") && StringUtils.isEmpty(userCode)) {
				continue;
			}
			try {
				list = readJdbcTemplate2.queryForList(sql, paramMap);
			} catch (Exception e) {
				log.error("活动执行失败！");
				continue;
			}
			log.info("---------list---------{}", list.size());
			if (null == list || list.size() == 0) {// 不满足条件
				continue;
			}
			double score = Double.parseDouble(list.get(0).get("score").toString());

			log.info("=============userCode========={}", userCode);
			TbSpScoreLogIn inlog = null;
			TbSpUser user = userDao.findByUserCode(userCode);
			List<TbSpScore> spScoreList = scoreDao.findByUserCode(userCode);
			TbSpScore spScore = null;
			BigDecimal s1 = new BigDecimal(score);
			// 抽奖活动-出单
			if (null != spOrder && Constants.LUCK_DRAW_ACTIVITY.equals(ac.getActivityType())) {
				log.info("---------抽奖活动记录---------");
				TbSpDrawLog draw = new TbSpDrawLog();
				draw.setActivityName(ac.getActivityName());
				draw.setActivityNo(ac.getActivityCode());
				// draw.setAmount(amount);
				draw.setUserCode(userCode);
				draw.setCreateTime(new Date());
				// draw.setDrawNo(drawNo);
				draw.setEffictiveDate(new Date());
				draw.setInvalidDate(ac.getPlanEndTime());
				draw.setRemark(ac.getRemark());
				draw.setGranter("system");
				draw.setOpenid(StringUtils.isNotEmpty(user.getWxOpenId()) ? user.getWxOpenId() : null);
				draw.setTelephone(StringUtils.isNotEmpty(user.getMobile()) ? user.getMobile() : null);
				draw.setStatus(Constants.TRUE);
				draw.setType(Constants.TRUE);
				draw.setPolicyNo(spOrder.getPolicyNo());
				drawLogDao.save(draw);
				// 抽奖次数减1
				// ac.setDrawBalance(ac.getDrawBalance() - 1);
				activityDao.save(ac);

				// 记录推送微信消息，获得一次抽奖机会
				Map<String, Object> tempMap = Maps.newHashMap();
				if (null != user) {
					tempMap.put("user", user);
				}
				if (StringUtils.isNotBlank(ac.getActivityName())) {
					tempMap.put("title", ac.getActivityName());
				}
				sendMsgList.add(tempMap);
				continue;
			}

			// 抽奖活动-分享
			if (null == spOrder && Constants.LUCK_DRAW_ACTIVITY.equals(ac.getActivityType())) {
				log.info("---------抽奖活动记录---------");
				TbSpDrawLog draw = new TbSpDrawLog();
				draw.setActivityName(ac.getActivityName());
				draw.setActivityNo(ac.getActivityCode());
				// draw.setAmount(amount);
				draw.setUserCode(userCode);
				draw.setCreateTime(new Date());
				// draw.setDrawNo(drawNo);
				draw.setEffictiveDate(new Date());
				draw.setInvalidDate(ac.getPlanEndTime());
				draw.setGranter("system");
				draw.setOpenid(StringUtils.isNotEmpty(user.getWxOpenId()) ? user.getWxOpenId() : null);
				draw.setTelephone(StringUtils.isNotEmpty(user.getMobile()) ? user.getMobile() : null);
				draw.setStatus(Constants.TRUE);
				draw.setType(Constants.APPROVE_ADD);
				// draw.setPolicyNo();
				drawLogDao.save(draw);
				// 抽奖次数减1
				// ac.setDrawBalance(ac.getDrawBalance() - 1);
				activityDao.save(ac);

				// 直接推送微信消息，获得一次抽奖机会，因为没有跟出单一起，所以跟发送顺序无关，不必添加到resultMap
				String title = ac.getActivityName();
				title = StringUtils.isNotBlank(title) ? "（" + title + "）" : "";
				String content = String.format(Constants.SMS_BY_ACTIVITY_TIMES, 1, title);
				boolean flag = weChatService.sendTextMessageSingle(user.getWxOpenId(), MessageType.REQ_MESSAGE_TYPE_TEXT, content);

				// 日志
				TbSpSaleLog saleLog = new TbSpSaleLog();
				saleLog.setOperation(TbSpSaleLog.WECHAT_MSG);
				saleLog.setUserCode(userCode);
				saleLog.setMark(TbSpSaleLog.WECHAT_MSG);
				saleLog.setRequestTime(new Date());
				saleLog.setRequestData("branchNo:" + branchNo + ",type：" + type + "<br>,user：" + JSON.toJSONString(user) + "<br>,spOrder："
						+ JSON.toJSONString(spOrder) + "<br>,content：" + content);
				saleLog.setResponseData("【抽奖】推送结果：" + flag);
				spSaleLogDao.save(saleLog);

				continue;
			}

			log.info("---------活动奖励积分---------{}", score);
			if (ac.getBalanceBudget() < score) {
				log.info("---------活动积分余额不足---不发放积分------{}", ac.getBalanceBudget());
				continue;
			}
			// 积分为0
			if (new BigDecimal(score).setScale(2, BigDecimal.ROUND_HALF_UP).compareTo(new BigDecimal("0.00")) == 0) {
				return resultMap;
			}

			if (null != spOrder) {// 出单活动
				log.info("---------出单活动奖励积分记录---------");
				log.info("=============出单活动spOrder.getProposalNo()========={}", spOrder.getProposalNo());
				if (CollectionUtils.isNotEmpty(spScoreList)) {
					spScore = spScoreList.get(0);
					BigDecimal s2 = new BigDecimal(spScore.getEffctiveScore());
					Double acscore = Math.floor(s2.add(s1).doubleValue());
					inlog = new TbSpScoreLogIn(Constants.CHANGE_TYYPE_ACTIVITY, Constants.FALSE,
							spScore.getEffctiveScore() < 0 ? (acscore > 0 ? acscore : 0) : score, score, score, ac.getApplyer(),
							spOrder.getPolicyNo(), ac.getActivityCode(), ac.getActivityName(), new Date(), "1", new Date(),
							DateUtil.changeDate(new Date(), Calendar.YEAR, scoreconfig.get(0).getPeriod()), userCode,
							StringUtils.isNotBlank(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotBlank(user.getWxOpenId()) ? user.getWxOpenId() : null, ac.getRemark(), "", "0000");
					spScore.setSumScore(Math.floor(s1.add(new BigDecimal(spScore.getSumScore())).doubleValue()));
					spScore.setEffctiveScore(acscore);
					spScore.setStatisticTime(new Date());
				} else {
					inlog = new TbSpScoreLogIn(Constants.CHANGE_TYYPE_ACTIVITY, Constants.FALSE, score, score, score, ac.getApplyer(),
							spOrder.getPolicyNo(), ac.getActivityCode(), ac.getActivityName(), new Date(), "1", new Date(),
							DateUtil.changeDate(new Date(), Calendar.YEAR, scoreconfig.get(0).getPeriod()), userCode,
							StringUtils.isNotBlank(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotBlank(user.getWxOpenId()) ? user.getWxOpenId() : null, ac.getRemark(), "", "0000");
					spScore = new TbSpScore(userCode, StringUtils.isNotEmpty(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotEmpty(user.getWxOpenId()) ? user.getWxOpenId() : null, score, score, 0.00, new Date(), "");
				}
			} else {
				log.info("---------一般活动奖励积分记录---------");
				if (CollectionUtils.isNotEmpty(spScoreList)) {
					spScore = spScoreList.get(0);
					BigDecimal s2 = new BigDecimal(spScore.getEffctiveScore());
					Double acscore = Math.floor(s2.add(s1).doubleValue());
					inlog = new TbSpScoreLogIn(Constants.CHANGE_TYYPE_ACTIVITY, Constants.FALSE,
							spScore.getEffctiveScore() < 0 ? (acscore > 0 ? acscore : 0) : score, score,
							spScore.getEffctiveScore() < 0 ? acscore : score, ac.getApplyer(), "", ac.getActivityCode(), ac.getActivityName(),
							new Date(), "1", new Date(), DateUtil.changeDate(new Date(), Calendar.YEAR, scoreconfig.get(0).getPeriod()), userCode,
							StringUtils.isNotBlank(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotBlank(user.getWxOpenId()) ? user.getWxOpenId() : null, ac.getRemark(), "", "0000");
					spScore.setSumScore(Math.floor(s1.add(new BigDecimal(spScore.getSumScore())).doubleValue()));
					spScore.setEffctiveScore(acscore);
					spScore.setStatisticTime(new Date());
				} else {
					inlog = new TbSpScoreLogIn(Constants.CHANGE_TYYPE_ACTIVITY, Constants.FALSE, score, score, score, ac.getApplyer(), "",
							ac.getActivityCode(), ac.getActivityName(), new Date(), "1", new Date(),
							DateUtil.changeDate(new Date(), Calendar.YEAR, scoreconfig.get(0).getPeriod()), userCode,
							StringUtils.isNotBlank(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotBlank(user.getWxOpenId()) ? user.getWxOpenId() : null, ac.getRemark(), "", "0000");
					spScore = new TbSpScore(userCode, StringUtils.isNotEmpty(user.getMobile()) ? user.getMobile() : null,
							StringUtils.isNotEmpty(user.getWxOpenId()) ? user.getWxOpenId() : null, score, score, 0.00, new Date(), "");
				}
			}

			log.info("---------活动奖励总积分记录---------");
			acList.add(inlog);
			scoreDao.save(spScore);
			scoreLogInDao.save(inlog);
			// 活动积分余额扣减
			BigDecimal dbs = new BigDecimal(ac.getBalanceBudget());
			ac.setBalanceBudget(dbs.subtract(s1).doubleValue());
			TbSpActivity db = activityDao.save(ac);
			// 低于预警值发短信
			if (db.getBalanceBudget() < db.getWarnBalance()) {
				StringBuilder content = new StringBuilder("活动：").append(db.getActivityName()).append(",积分余额").append(db.getBalanceBudget())
						.append(",低于设置的预警值").append(db.getWarnBalance()).append(",请及时追加预算！");
				if (StringUtils.isNotEmpty(db.getWarnEmail())) {// 发送邮箱
					List<String> toEmils = Lists.newArrayList();
					toEmils.add(db.getWarnEmail());
					try {
						emailService.sendEmail("活动积分余额预警", content.toString(), toEmils);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					} catch (MessagingException e) {
						e.printStackTrace();
					}
				}
			}
			sumScore = sumScore.add(s1);
		}
		resultMap.put("acList", acList);// 活动记录
		resultMap.put("sendMsgList", sendMsgList);// 抽奖消息发送记录
		return resultMap;
	}

	@Override
	public ServiceResult approveHistory(String type, Integer id, Integer pageNumber, Integer pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.DESC, "id");
		Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
		if ("all".equals(type)) {
			sr.setResult(approveDao.findActivityByApproveId(id.toString(), pageable));
		} else {
			sr.setResult(approveDao.findByTypeAndApproveId(type, id.toString(), pageable));
		}
		return sr;
	}

	/**
	 * 定时任务：处理过期积分、非即时生效的积分
	 * 
	 * @return
	 */
	@Override
	public ServiceResult task() {
		log.info("开始执行定时任务：" + DateUtil.dateFromat(new Date(), DateUtil.DATE_TIME_PATTERN2));

		/** =====处理过期积分======= */
		ServiceResult sr = new ServiceResult();
		sr.setSuccess();
		log.info("开始定时任务。。。。。。");
		try {
			log.info("查询过期积分记录");
			// 查询过期积分记录
			List<TbSpScoreLogIn> invalidateList = scoreLogInDao.findInvalidate();
			if (CollectionUtils.isNotEmpty(invalidateList)) {
				log.info("定时任务查询过期积分记录：" + invalidateList.size());
				TbSpScoreLogOut outLog = null;
				String reasonStr = DateUtil.dateFromat(new Date(), DateUtil.PATTERN_YYYY_MM_CH) + "到期宝豆";
				List<TbSpScoreLogOut> outList = Lists.newArrayList();
				for (TbSpScoreLogIn inlog : invalidateList) {
					outLog = new TbSpScoreLogOut();
					outLog.setUserCode(inlog.getUserCode());
					outLog.setChangeType(Constants.CHANGE_TYYPE_INVALID);
					outLog.setChangeTime(new Date());
					outLog.setReason(reasonStr);
					outLog.setPolicyNo(StringUtils.isNotBlank(inlog.getPolicyNo()) ? inlog.getPolicyNo() : null);
					outLog.setReasonNo(String.valueOf(inlog.getId()));
					outLog.setReChangeScore(inlog.getBalance() * (-1));
					outLog.setAcChangeScore(inlog.getBalance() * (-1));
					outLog.setGranter("system");
					outLog.setStatus("1");
					outLog.setRemark("过期积分");
					outLog.setEffictiveDate(new Date());
					outLog.setInvalidDate(new Date());
					outLog.setTelephone(inlog.getTelephone());
					outLog.setOpenId(inlog.getOpenid());

					log.info("过期积分{}", inlog.getBalance());
					scoreDao.reduceScore(inlog.getBalance(), inlog.getUserCode());// 减少有效积分
					inlog.setBalance(0.0);
					scoreLogInDao.save(inlog);
					outList.add(outLog);
				}
				scoreLogOutDao.saveAll(outList);
				log.info("定时任务处理过期积分结束end");
			} else {
				log.info("未查询到过期积分");
			}
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务处理过期积分发生异常：" + e.getMessage());
			log.error("定时任务处理过期积分发生异常：" + e.getMessage(), e);
		}
		/** =====处理未生效积分======= */
		try {
			log.info("查询未生效积分记录");
			// 查询未生效积分记录
			List<TbSpScoreLogIn> effictiveList = scoreLogInDao.findNoeffictive();
			if (CollectionUtils.isNotEmpty(effictiveList)) {
				log.info("定时任务查询未生效积分记录条数：{}", effictiveList.size());
				for (TbSpScoreLogIn inlog : effictiveList) {
					log.info("用户{}", inlog.getUserCode());
					log.info("未生效积分记录：{}", inlog.getReChangeScore());
					List<TbSpScore> dbscore = scoreDao.findByUserCode(inlog.getUserCode());
					BigDecimal rechange = new BigDecimal(inlog.getReChangeScore());// 应发积分
					BigDecimal effective = new BigDecimal(dbscore.get(0).getEffctiveScore());// 已生效积分
					BigDecimal acChange = new BigDecimal(inlog.getAcChangeScore());// 实发积分，未生效前为0
					Double acscore = rechange.subtract(acChange).add(effective).doubleValue();
					if (effective.doubleValue() < 0) {// 有效积分为负
						inlog.setBalance(acscore > 0 ? acscore : 0);// 补齐欠额
					} else {
						inlog.setBalance(inlog.getReChangeScore());
					}
					scoreDao.updateEffctiveScore(inlog.getReChangeScore(), inlog.getUserCode());
					inlog.setAcChangeScore(inlog.getReChangeScore());
					scoreLogInDao.save(inlog);
				}
			} else {
				log.info("未查询到待生效积分");
			}
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务处理未生效积分发生异常：" + e.getMessage());
			log.error("定时任务处理未生效积分发生异常：" + e.getMessage(), e);
		}

		try {
			log.info("查询活动预警");
			/** ==活动预警== */
			List<TbSpActivity> waringList = activityDao.findWarningActivity();
			if (CollectionUtils.isNotEmpty(waringList)) {
				for (TbSpActivity t : waringList) {
					StringBuilder content = new StringBuilder("活动：").append(t.getActivityName()).append(",积分余额").append(t.getBalanceBudget())
							.append(",低于设置的预警值").append(t.getWarnBalance()).append(",请及时追加预算！");
					this.warn(content.toString(), t.getWarnEmail(), t.getWarnPhoneNo());
				}
			} else {
				log.info("未查询到活动预警");
			}
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务活动预警提醒发生异常：" + e.getMessage());
			log.error("定时任务处理活动预警提醒发生异常：" + e.getMessage(), e);
		}

		try {
			// 活动未及时审批
			log.info("查询活动未及时审批");
			List<TbSpActivity> acList = activityDao.findExpireNotApprove();
			if (CollectionUtils.isNotEmpty(acList)) {
				log.info("定时任务查询活动未及时审批记录：{}", acList.size());
				for (TbSpActivity ac : acList) {
					activityDao.updateStatus(Constants.NOT_IN_TIME, ac.getId());
					TbSpApprove dbapp = approveDao.findByTypeAndApproveId(Constants.ACTIVITY_APPROVE, ac.getId().toString(), Constants.APPROVE_WAIT);
					dbapp.setStatus(Constants.APPROVE_NO);
					dbapp.setApproveTime(new Date());
					dbapp.setUserId("system");
					dbapp.setUserName("system");
					approveDao.save(dbapp);
				}
			} else {
				log.info("未查询到活动未及时审批");
			}
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务处理活动未及时审批发生异常：" + e.getMessage());
			log.error("定时任务处理活动未及时审批发生异常：" + e.getMessage(), e);
		}

		try {
			log.info("查询活动到期结束");
			// 活动到期结束
			List<TbSpActivity> overList = activityDao.findOverActivity();
			if (CollectionUtils.isNotEmpty(overList)) {
				log.info("定时任务查询活动到期结束条数：{}", overList.size());
				for (TbSpActivity ac : overList) {
					// activityDao.updateStatus(Constants.EXPIRE, ac.getId());
					ac.setStatus(Constants.EXPIRE);
					ac.setActualEndTime(new Date());
					activityDao.save(ac);
				}
			} else {
				log.info("未查询到到期活动");
			}
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务处理活动到期结束发生异常：" + e.getMessage());
			log.error("定时任务处理活动到期结束发生异常：" + e.getMessage(), e);
		}

		try {
			log.info("访问量统计");
			SimpleDateFormat df = new SimpleDateFormat(DateUtil.DATE_TIME_PATTERN2);// 设置日期格式
			String startYear = DateUtil.getThisYearFirstDate();
			log.info("本年开始：{}", startYear);
			String endYear = DateUtil.getThisYearLastDate();
			log.info("本年结束：{}", endYear);
			homePageService.visitTask(startYear, endYear, "year");
			String startMonth = DateUtil.getThisMonthFirstDate();
			log.info("本月开始：{}", startMonth);
			String endMonth = df.format(DateUtil.getLastDayOfThisMonth());
			log.info("本月结束：{}", endMonth);
			homePageService.visitTask(startMonth, endMonth, "month");
			String startWeek = df.format(DateUtil.getWeekStartDate());
			log.info("本周开始：{}", startWeek);
			String endWeek = df.format(DateUtil.dayOffset(DateUtil.getWeekStartDate(), 7));
			log.info("本周结束：{}", endWeek);
			homePageService.visitTask(startWeek, endWeek, "week");
		} catch (Exception e) {
			sr.setAppFail();
			sr.setResult("定时任务处理访问量统计：" + e.getMessage());
			log.error("定时任务处理访问量统计：" + e.getMessage(), e);
		}

		log.info("结束执行定时任务：" + DateUtil.dateFromat(new Date(), DateUtil.DATE_TIME_PATTERN2));

		return sr;
	}

	@Override
	public ServiceResult queryDrawTimes(String userCode) {
		// String test = Current.userCodeBs.get();
		ServiceResult sr = new ServiceResult();
		List<TbSpDrawLog> drawList = drawLogDao.findByUserCode(userCode);
		log.info("抽奖次数-------------------{}", drawList.size());
		if (CollectionUtils.isNotEmpty(drawList)) {
			sr.setSuccess();
			sr.setResult(drawList.size());
		} else {
			sr.setFail();
		}
		return sr;
	}

	/**
	 * 预警
	 * @param content
	 * @param email
	 * @param mobile
	 * @throws UnsupportedEncodingException
	 * @throws MessagingException
	 */
	private void warn(String content, String email, String mobile) throws UnsupportedEncodingException, MessagingException {
		if (StringUtils.isNotEmpty(email)) {// 发送邮箱
			List<String> toEmils = Lists.newArrayList();
			toEmils.add(email);
			emailService.sendEmail("活动积分余额预警", content.toString(), toEmils);
		}
		if (StringUtils.isNotEmpty(mobile)) {// 发送短信
			SmsService.smsToMobile(mobile, content.toString());
		}
	}

	@Override
	public ServiceResult draw(String userCode) {
		ServiceResult sr = new ServiceResult();
		TbSpSaleLog saleLog = new TbSpSaleLog();
		StringBuilder msg = new StringBuilder();
		sr.setFail();
		msg.append("userCode:" + userCode);
		List<TbSpOrder> orderList = null;
		// 判断是否为没有抽奖次数 如果没有 保存抽奖记录抽奖设置为0 并且积分信息不保存
		boolean isNoDrawBalance = false;
		try {
			List<TbSpScoreConfig> scoreconfig = (List<TbSpScoreConfig>) redisUtils.get(Constants.SCORE_CONFIG_INFO);
			if (CollectionUtils.isEmpty(scoreconfig)) {
				scoreconfig = scoreConfigDao.findAllConfig();
				redisUtils.set(Constants.SCORE_CONFIG_INFO, scoreconfig);
			}
			List<TbSpDrawLog> drawList = drawLogDao.findByUserCode(userCode);
			log.info("抽奖次数：", drawList.size());
			if (CollectionUtils.isEmpty(drawList)) {
				msg.append(" -  无抽奖机会啦!");
				sr.setResult("无抽奖机会啦!");
				return sr;
			}
			TbSpDrawLog draw = drawList.get(0);

			List<TbSpActivity> activitys = activityDao.findByActivityCode(draw.getActivityNo());
			log.info("活动个数：", activitys.size());
			if (CollectionUtils.isEmpty(activitys)) {
				msg.append(" -  活动结束,请下次再参与!");
				sr.setResult("活动结束,请下次再参与!");
				return sr;
			}
			TbSpActivity activity = activitys.get(0);
			if (activity.getDrawBalance() <= 0) {
				isNoDrawBalance = true;
				// sr.setSuccess();
				// sr.setResult("谢谢参与!");
				// return sr;
			}
			List<TbSpScoreConfig> scoreconfigs = (List<TbSpScoreConfig>) redisUtils.get(Constants.SCORE_CONFIG_INFO);
			if (CollectionUtils.isEmpty(scoreconfigs)) {
				scoreconfigs = scoreConfigDao.findAllConfig();
				redisUtils.set(Constants.SCORE_CONFIG_INFO, scoreconfigs);
			}
			TbSpScoreConfig scf = scoreconfigs.get(0);
			if (scf == null) {
				scf = new TbSpScoreConfig(3, 100d);// 默认,避免报错
			}
			double amount = 0.0;
			Double balance = activity.getBalanceBudget(); // 预算总额
			Double amountLimitation = activity.getAmountLimitation();
			// 保费比例
			Double policyRate = activity.getPolicyRate();
			if (null == policyRate) {
				policyRate = 0.0;
			}
			Double policyPrice = 0.0;
			if (StringUtils.isNotBlank(draw.getPolicyNo())) {
				orderList = orderDao.findByPolicyNo(draw.getPolicyNo());
				if (policyRate != null && policyRate > 0 && orderList != null && orderList.size() > 0) {
					policyPrice = orderList.get(0).getAmount() * scoreconfigs.get(0).getRate() * policyRate;
				}

			}

			int drawBalance = activity.getDrawBalance();// 剩余抽奖剩余次数
			if (null != activity.getSpecialValue() && null != activity.getSpecialTimes() && activity.getSpecialTimes() > 0
					&& activity.getSpecialValue() > 0) {// 特殊金额的红包
				// List<TbSpDrawLog> specailList = drawLogDao.findSpecialByUsercode(userCode,
				// activity.getActivityCode(), activity.getSpecialValue());
				List<TbSpDrawLog> specailList = drawLogDao.findSpecial(activity.getActivityCode(), activity.getSpecialValue());
				// 查找是否有特殊中奖金额
				if (null == specailList) {
					specailList = Lists.newArrayList();
				}
				if (specailList.size() < activity.getSpecialTimes() && balance > 0) {// 特殊红包未发完
					// 抽奖次数小于特殊红包剩余个数, 必中
					if (drawBalance <= activity.getSpecialTimes() - specailList.size()) {
						amount = activity.getSpecialValue() < balance ? activity.getSpecialValue() : balance;
					} else if (RedPacketsUtil.random(drawBalance / (activity.getSpecialTimes() - specailList.size()))) {// 随机产生
						amount = activity.getSpecialValue();
					}
					// BigDecimal bean = new BigDecimal(amount).multiply(new
					// BigDecimal(scf.getRate()));// 宝豆
				}
			}
			msg.append("<br>设置上限宝豆:" + amountLimitation + "<br>保单最高赠送宝豆:" + policyPrice);
			if (policyPrice < amountLimitation) {
				amountLimitation = policyPrice;
			}
			msg.append("<br>是否特殊金额:" + amount);
			if (amount <= 0.0) {
				double minVaule = null != activity.getMinValue() && activity.getMinValue() > 0 ? activity.getMinValue() / scf.getRate() : 1;
				Double sendMinValue = activity.getMinValue();
				if (sendMinValue == null) {
					sendMinValue = 1.0;
				}
				int maxTimes = null != activity.getMaxTimes() && activity.getMinValue() > 0 ? activity.getMaxTimes() : 2;// 单个红包平均数的倍数
				if (balance > 0) {
					amount = RedPacketsUtil.spiltRedPacket(balance / scf.getRate(), drawBalance, minVaule, maxTimes);// 中奖金额
				}
				// BigDecimal bean = new BigDecimal(amount).multiply(new
				// BigDecimal(scf.getRate()));// 宝豆
				// bean=bean.setScale(0, BigDecimal.ROUND_HALF_UP);

				BigDecimal bean = new BigDecimal(amount);// 宝豆
				bean = bean.setScale(2, BigDecimal.ROUND_HALF_UP);
				amount = bean.doubleValue();

				// amount 0.45 为抽到的钱， res 转换为宝豆
				BigDecimal res = new BigDecimal(amount).multiply(new BigDecimal(scf.getRate()));
				res = res.setScale(0, BigDecimal.ROUND_HALF_UP);
				amount = res.doubleValue();
				msg.append("<br>最小限制宝豆:" + sendMinValue);
				msg.append("<br>微信红包抽奖算法:" + amount);

				// 如果限制了每个红包的最大值 必须在一定范围内
				if (amountLimitation != null && amountLimitation != 0 && amountLimitation > 0 && amount > amountLimitation) {
					if (amountLimitation > sendMinValue) {
						amount = Math.random() * (amountLimitation - sendMinValue) + sendMinValue;
						msg.append("<br>重新抽奖金额为:" + amount);
						BigDecimal beanRan = new BigDecimal(amount);// 宝豆
						amount = beanRan.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
					} else {
						amount = sendMinValue;
					}
					if (amount > amountLimitation) {
						msg.append("<br>重新抽奖超过限制:" + amount);
						amount = sendMinValue;
					}

				}

			} else {
				// 特殊金额处理
				if (amount >= amountLimitation) {
					amount = amountLimitation;
				}
			}
			// msg.append(" - isNoDrawBalance:" + isNoDrawBalance);

			// 没有余额的情况 或者抽奖出来的金额大于剩余的余额
			if (activity.getBalanceBudget() <= 0 || amount > activity.getBalanceBudget()) {
				isNoDrawBalance = true;
			}

			if (isNoDrawBalance) {
				amount = 0;
			}
			draw.setAmount(amount);
			draw.setStatus("2");// 已经抽奖
			draw.setDrawTime(new Date());

			// 更新积分

			TbSpScoreLogIn inlog = new TbSpScoreLogIn(Constants.CHANGE_TYYPE_ACTIVITY, Constants.FALSE, amount, amount, amount, activity.getApplyer(),
					draw.getPolicyNo(), activity.getActivityCode(), activity.getActivityName(), new Date(), "1", new Date(),
					DateUtil.changeDate(new Date(), Calendar.YEAR, scf.getPeriod()), userCode, draw.getTelephone(), draw.getOpenid(),
					activity.getRemark(), "", "0000");
			BigDecimal balanceBudget = new BigDecimal(activity.getBalanceBudget());
			activity.setBalanceBudget(balanceBudget.subtract(new BigDecimal(amount)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());

			if (!isNoDrawBalance) {
				activity.setDrawBalance(activity.getDrawBalance() - 1);// 抽奖次数减一
			}

			if (activity.getBalanceBudget() <= activity.getWarnBalance()
					&& (StringUtil.isNotEmpty(activity.getWarnEmail()) || StringUtil.isNotEmpty(activity.getWarnPhoneNo()))) {// 达到预警条件
				try {
					if (Constants.FALSE.equals(activity.getHasRemind())) {// 是否发送过提醒
						StringBuilder content = new StringBuilder("活动：").append(activity.getActivityName()).append(",积分余额")
								.append(activity.getBalanceBudget()).append(",低于设置的预警值").append(activity.getWarnBalance()).append(",请及时追加预算！");
						this.warn(content.toString(), activity.getWarnEmail(), activity.getWarnPhoneNo());
						activity.setHasRemind(Constants.TRUE);
						activityDao.save(activity);
					}
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			}
			msg.append("<br>用户:" + userCode + "获得抽奖宝豆:" + amount);
			// 更新积分表
			saleLog.setResponseData(msg.toString());
			saleLog.setUserCode(userCode);
			saleLog.setRequestData(draw.getPolicyNo());
			saleLog.setOperation("抽奖");
			saleLog.setMark("抽奖");

			// 不保存积分
			if (!isNoDrawBalance) {
				scoreLogInDao.save(inlog);
			}

			List<TbSpScore> list = scoreDao.findByUserCode(userCode);
			if (CollectionUtils.isNotEmpty(list)) {
				scoreDao.addScore(amount, userCode);
			} else {// 新建记录
				TbSpUser user = userDao.findByUserCode(userCode);
				TbSpScore spScore = new TbSpScore(userCode, StringUtils.isNotEmpty(user.getMobile()) ? user.getMobile() : null,
						StringUtils.isNotEmpty(user.getWxOpenId()) ? user.getWxOpenId() : null, amount, amount, 0.00, new Date(), "");
				scoreDao.save(spScore);
			}

			activityDao.save(activity);
			saleLog.setRequestData("抽奖ID" + draw.getId().toString());
			drawLogDao.save(draw);
			// sr.setResult(amount);

			sr.setResult(amount);
			sr.setSuccess();
		} catch (Exception e) {
			msg.append("  异常:" + e.getMessage());
			log.error(e.getMessage(), e);
			sr.setResult("服务器鸭梨山大,请稍后再试!");
		}

		// 设置为谢谢参与
		if (isNoDrawBalance) {
			sr.setSuccess();
			sr.setResult("谢谢参与!");
		}
		spSaleLogDao.save(saleLog);
		return sr;
	}

	@Override
	public ServiceResult getActivityGreatBenefit() {
		ServiceResult sr = new ServiceResult();
		Map<String, Object> map = Maps.newHashMap();

		List<Integer> idlists = new ArrayList<>();
		for (String id : this.productIds) {
			if (StringUtils.isNotBlank(id)) {
				idlists.add(Integer.parseInt(id));
			}
		}
		List<TbSpProduct> products = productDao.findInIds(idlists);
		map.put("products", products);

		Map<String, Object> greatBenefit = Maps.newHashMap();
		greatBenefit.put("title", this.title);
		greatBenefit.put("desc", this.desc);
		greatBenefit.put("imgUrl", this.imgUrl);

		map.put("greatBenefit", greatBenefit);

		sr.setResult(map);
		sr.setSuccess();
		return sr;
	}

}
